<template>
  <div class="user-management-container">
    <div class="page-header">
      <h2>用户管理</h2>
      <p class="subtitle">系统用户数据管理与维护</p>
    </div>

    <el-card shadow="hover" class="search-card">
      <div class="search-area">
        <div class="search-inputs">
          <el-input
            v-model="search.username"
            placeholder="请输入用户名"
            prefix-icon="Search"
            clearable
            @change="onSearchChange"
          />
          <el-input
            v-model="search.nickname"
            placeholder="请输入昵称"
            prefix-icon="User"
            clearable
            @change="onSearchChange"
          />
          <el-input
            v-model="search.mobile"
            placeholder="请输入电话号码"
            prefix-icon="Phone"
            clearable
            @change="onSearchChange"
          />
          <el-input
            v-model="search.email"
            placeholder="请输入邮箱"
            prefix-icon="Message"
            clearable
            @change="onSearchChange"
          />
        </div>

        <div class="filter-area">
          <el-select
            v-model="filter.gender"
            placeholder="请选择性别"
            clearable
            @change="onFilterChange"
          >
            <el-option
              v-for="item in filterOptions.gender"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>

          <el-select
            v-model="filter.status"
            placeholder="请选择状态"
            clearable
            @change="onFilterChange"
          >
            <el-option
              v-for="item in filterOptions.status"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </div>
      </div>
    </el-card>

    <div class="action-bar">
      <div class="left-section">
        <el-button type="primary" :icon="Plus" @click="plusRow"
          >添加用户</el-button
        >
        <el-button type="danger" :icon="Delete" @click="deleteAll"
          >删除选中</el-button
        >
      </div>
      <div class="right-section">
        <el-tooltip content="刷新数据" placement="top">
          <el-button :icon="RefreshRight" circle @click="getPage" />
        </el-tooltip>
      </div>
    </div>

    <el-card shadow="hover" class="table-card">
      <el-table
        ref="tableRef"
        :data="tableData"
        @sort-change="sortChange"
        tooltip-effect="light"
        :show-overflow-tooltip="true"
        border
        stripe
        highlight-current-row
        style="width: 100%"
      >
        <el-table-column type="selection" width="50" align="center" />
        <el-table-column prop="username" label="用户名" sortable width="120" />
        <el-table-column
          prop="avatar"
          label="头像"
          width="100px"
          align="center"
        >
          <template #default="scope">
            <el-image
              :src="scope.row.avatar"
              class="activity-img"
              fit="cover"
              :preview-src-list="[scope.row.avatar]"
              preview-teleported
            />
          </template>
        </el-table-column>
        <el-table-column
          prop="nickname"
          label="昵称"
          sortable
          min-width="120"
        />
        <el-table-column
          prop="gender"
          label="性别"
          sortable
          width="80"
          align="center"
        >
          <template #default="scope">
            <el-tag
              :type="scope.row.gender === 'F' ? 'danger' : 'primary'"
              effect="plain"
              size="small"
              round
            >
              {{ scope.row.gender === "F" ? "女" : "男" }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="mobile" label="电话" sortable width="130" />
        <el-table-column prop="email" label="邮箱" sortable min-width="180" />
        <el-table-column
          prop="role"
          label="角色"
          sortable
          width="120"
          align="center"
        >
          <template #default="scope">
            <el-tag
              :type="statusRoleMap[scope.row.role]?.type || 'info'"
              effect="light"
              size="small"
            >
              {{ statusRoleMap[scope.row.role]?.text || "未知角色" }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          prop="status"
          label="状态"
          sortable
          width="100"
          align="center"
        >
          <template #default="scope">
            <el-tag
              :type="scope.row.status === 1 ? 'success' : 'info'"
              effect="dark"
              size="small"
            >
              {{ statusUserMap[scope.row.status]?.text || "未知状态" }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column fixed="right" label="操作" width="150" align="center">
          <template #default="scope">
            <el-button
              type="primary"
              size="small"
              :icon="Edit"
              circle
              @click="editRow(scope)"
            />
            <el-button
              type="danger"
              size="small"
              :icon="Delete"
              circle
              @click="deleteRow(scope)"
            />
            <el-tooltip
              :content="scope.row.status === 1 ? '禁用账号' : '启用账号'"
              placement="top"
            >
              <el-switch
                v-model="scope.row.status"
                :active-value="1"
                :inactive-value="0"
                @change="() => switchChange(scope.row)"
                style="margin-left: 10px"
              />
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination-container">
        <el-pagination
          v-model:current-page="pagination.page"
          v-model:page-size="pagination.size"
          :page-sizes="[10, 20, 50, 100]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="pagination.total"
          @size-change="onPaginationChange"
          @current-change="onPaginationChange"
          background
        />
      </div>
    </el-card>

    <el-dialog
      v-model="plusAndEditDialog.isVisible"
      :title="
        plusAndEditDialog.title === '添加' ? '添加新用户' : '编辑用户信息'
      "
      width="500px"
      ref="formRef"
      align-center
      destroy-on-close
    >
      <el-form
        label-width="80px"
        :model="plusAndEditForm"
        :rules="rules"
        ref="formRef"
        label-position="right"
        status-icon
      >
        <el-row :gutter="20">
          <el-col :span="10">
            <el-form-item label="头像" prop="avatar">
              <div class="upload-container">
                <el-image
                  :src="plusAndEditForm.avatar"
                  class="preview-image"
                  fit="cover"
                >
                  <template #error>
                    <div class="image-placeholder">
                      <span>暂无图片</span>
                    </div>
                  </template>
                </el-image>
                <el-upload
                  class="image-uploader"
                  :http-request="customUpload"
                  :limit="1"
                  v-model:file-list="fileList"
                  :on-error="handleError"
                  :before-remove="beforeRemove"
                  :on-exceed="handleExceed"
                  drag
                >
                  <el-icon class="el-icon--upload"><Upload /></el-icon>
                  <div class="el-upload__text">
                    拖拽文件到此处或<em>点击上传</em>
                  </div>
                  <template #tip>
                    <div class="el-upload__tip">
                      支持 jpg/png 格式，文件大小不超过 500KB
                    </div>
                  </template>
                </el-upload>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="用户名" prop="username">
              <el-input
                v-model="plusAndEditForm.username"
                placeholder="请输入用户名"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="昵称" prop="nickname">
              <el-input
                v-model="plusAndEditForm.nickname"
                placeholder="请输入昵称"
              />
            </el-form-item>
          </el-col>
        </el-row>

        <el-form-item label="密码" prop="password">
          <el-input
            v-model="plusAndEditForm.password"
            placeholder="请输入密码"
            show-password
          />
        </el-form-item>

        <el-form-item label="角色" required>
          <el-select
            v-model="plusAndEditForm.role"
            placeholder="请选择角色"
            style="width: 100%"
          >
            <el-option
              v-for="(value, key) in statusRoleMap"
              :key="key"
              :label="value.text"
              :value="parseInt(key)"
            />
          </el-select>
        </el-form-item>

        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="电话">
              <el-input
                v-model="plusAndEditForm.mobile"
                placeholder="请输入电话"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="邮箱">
              <el-input
                v-model="plusAndEditForm.email"
                placeholder="请输入邮箱"
              />
            </el-form-item>
          </el-col>
        </el-row>

        <el-form-item label="性别">
          <el-radio-group v-model="plusAndEditForm.gender">
            <el-radio value="M">男</el-radio>
            <el-radio value="F">女</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="状态">
          <el-switch
            v-model="plusAndEditForm.status"
            :active-value="1"
            :inactive-value="0"
            active-text="启用"
            inactive-text="禁用"
            inline-prompt
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="plusAndEditDialog.isVisible = false"
            >取消</el-button
          >
          <el-button type="primary" @click="save(formRef)">确认保存</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted } from "vue";
import {
  adminPage,
  adminDeleteByUserId,
  adminDeleteBatch,
  adminAdd,
  adminEdit,
} from "@/apis/admin/user";
import {
  Delete,
  Edit,
  Plus,
  Search,
  User,
  Phone,
  Message,
  RefreshRight,
} from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { upload } from "@/apis/upload";
// 存储表格数据的变量
const tableData = ref([]);

// 搜索输入框搜索条件
const search = reactive({
  username: "",
  nickname: "",
  mobile: "",
  email: "",
});

/**
 * 搜索输入框对应的触发事件
 */
const onSearchChange = () => {
  pagination.page = 1; // 重置为第一页
  getPage();
};

// 过滤对应的条件
const filter = reactive({
  gender: null,
  status: null,
});

/**
 * 过滤下拉框对应的触发事件
 */
const onFilterChange = () => {
  pagination.page = 1; // 重置为第一页
  getPage();
};

// 过滤对应的选项
const filterOptions = reactive({
  gender: [
    {
      label: "男",
      value: "M",
    },
    {
      label: "女",
      value: "F",
    },
  ],
  status: [
    {
      label: "启用",
      value: 1,
    },
    {
      label: "禁用",
      value: 0,
    },
  ],
});

// 存储排序字段
const orders = reactive({
  column: "id",
  isAsc: true,
});

/**
 * 表格排序函数
 * @param {Object} param0 排序参数
 */
const sortChange = ({ prop, order }) => {
  Object.assign(orders, {
    column: prop,
    isAsc: order === "ascending",
  });
  getPage();
};

/**
 * 删除一行
 * @param {Object} scope 行数据
 */
const deleteRow = (scope) => {
  ElMessageBox.confirm(
    `确定要删除用户 "${scope.row.username}" 吗?`,
    "删除确认",
    {
      confirmButtonText: "确定删除",
      cancelButtonText: "取消",
      type: "warning",
    }
  )
    .then(() => {
      adminDeleteByUserId(scope.row.id)
        .then(() => {
          ElMessage.success("删除成功");
          getPage();
        })
        .catch(() => {
          ElMessage.error("删除失败");
        });
    })
    .catch(() => {
      ElMessage.info("已取消删除");
    });
};

/**
 * 获取表格组件引用对象
 */
const tableRef = ref();

/**
 * 删除所有选中行
 */
const deleteAll = async () => {
  const selectionRows = tableRef.value.getSelectionRows();

  if (selectionRows.length === 0) {
    ElMessage.warning("请至少选择一条记录");
    return;
  }

  const usernames = selectionRows.map((row) => row.username).join("、");
  const ids = selectionRows.map((row) => row.id);

  ElMessageBox.confirm(
    `确定要删除选中的 ${selectionRows.length} 位用户吗?`,
    "批量删除确认",
    {
      confirmButtonText: "确定删除",
      cancelButtonText: "取消",
      type: "warning",
    }
  )
    .then(async () => {
      try {
        await adminDeleteBatch(ids);
        ElMessage.success(`成功删除 ${selectionRows.length} 条记录`);
        getPage();
      } catch (error) {
        ElMessage.error("批量删除失败");
      }
    })
    .catch(() => {
      ElMessage.info("已取消删除");
    });
};

/**
 * 分页查询
 */
const getPage = () => {
  adminPage(
    {
      filter: filter,
      search: search,
      orders: [orders],
    },
    pagination.page,
    pagination.size
  )
    .then((result) => {
      tableData.value = result.data.records;
      pagination.total = result.data.total;
    })
    .catch(() => {
      ElMessage.error("获取数据失败");
    });
};

// 分页
const pagination = reactive({
  page: 1,
  size: 10,
  total: 0,
});

/**
 * 分页改变函数
 */
const onPaginationChange = () => {
  getPage();
};

/**
 * 添加和修改表格数据
 */
const plusAndEditForm = reactive({
  username: "",
  nickname: "",
  password: "",
  role: 1,
  gender: "M",
  mobile: "",
  email: "",
  status: 1,
  avatar: "",
});

// 表单验证规则
const formRef = ref();
// 密码校验函数
const validatePass = (rule, value, callback) => {
  if (value === "") {
    callback(new Error("请输入密码"));
  } else {
    if (value.length < 6) {
      callback(new Error("密码长度至少6位"));
    }
    if (!/[A-Z]/.test(value)) {
      callback(new Error("密码需包含大写字母"));
    }
    if (!/[0-9]/.test(value)) {
      callback(new Error("密码需包含数字"));
    }
    callback();
  }
};
// 表单校验规则
const rules = reactive({
  username: [
    { required: true, message: "用户名不能为空", trigger: "blur" },
    { min: 3, max: 25, message: "用户名长度为3~25", trigger: "blur" },
  ],
  password: [{ required: true, validator: validatePass, trigger: "blur" }],
  email: [
    { required: true, message: "邮箱不能为空", trigger: "blur" },
    { type: "email", message: "请输入正确的邮箱格式", trigger: "blur" },
  ],
  phone: [
    { required: true, message: "手机号不能为空", trigger: "blur" },
    {
      pattern: /^1[3-9]\d{9}$/,
      message: "请输入正确的手机号",
      trigger: "blur",
    },
  ],
  captcha: [
    { required: true, message: "验证码不能为空", trigger: "blur" },
    { min: 4, max: 6, message: "请输入正确的验证码", trigger: "blur" },
  ],
});

/**
 * 添加和修改的对话框
 */
const plusAndEditDialog = reactive({
  isVisible: false,
  title: "",
});

// 定义一个初始状态对象
const defaultForm = {
  // 设置默认值
  username: "",
  nickname: "",
  password: "",
  role: 1,
  gender: "",
  mobile: "",
  email: "",
  status: 0,
  avatar: "",
};

/**
 * 修改当前行的数据
 * @param {Object} scope 行数据
 */
const editRow = (scope) => {
  fileList.value = []; // 清空上传文件列表
  // 先重置表单为默认值
  Object.assign(plusAndEditForm, defaultForm);
  // 然后用行数据覆盖默认值
  Object.assign(plusAndEditForm, scope.row);
  plusAndEditDialog.isVisible = true;
  plusAndEditDialog.title = "修改";
  console.log(plusAndEditForm);
};

/**
 * 添加一行数据
 */
const plusRow = () => {
  fileList.value = []; // 清空上传文件列表
  // 重置表单为默认值
  Object.assign(plusAndEditForm, defaultForm);
  plusAndEditDialog.isVisible = true;
  plusAndEditDialog.title = "添加";
  console.log(plusAndEditForm);
};

/**
 * 修改和添加的保存功能
 */
const save = async (formRef) => {
  try {
    formRef.validate(async (valid) => {
      if (valid) {
        if (plusAndEditDialog.title === "添加") {
          await adminAdd(plusAndEditForm);
          ElMessage.success("添加成功");
        } else {
          await adminEdit(plusAndEditForm);
          ElMessage.success("修改成功");
        }
        plusAndEditDialog.isVisible = false;
        getPage();
      } else {
        ElMessage.error("表单验证失败，请检查输入");
      }
    });
  } catch (error) {
    ElMessage.error("保存失败,完善表单");
  }
};

/**
 * 更改用户状态
 * @param {Object} row 行数据
 */
const switchChange = async (row) => {
  try {
    await adminEdit(row);
    ElMessage.success(
      `已${row.status === 1 ? "启用" : "禁用"}用户 ${row.username}`
    );
    getPage();
  } catch (error) {
    ElMessage.error("状态更改失败");
    // 恢复状态
    row.status = row.status === 1 ? 0 : 1;
  }
};

// 生命周期
onMounted(() => {
  // 页面加载的时候立刻执行一次请求
  getPage();
});

// 用户状态
const statusUserMap = {
  0: { text: "已禁用", type: "info" },
  1: { text: "已启用", type: "success" },
};

// 角色类型
const statusRoleMap = {
  1: { text: "普通用户", type: "info" },
  2: { text: "管理员", type: "primary" },
};

// 上传文件
let fileList = ref([]);

// 上传失败回调
function handleError(error, file, fileList) {
  console.error("上传失败：", error);
  ElMessage.error("上传失败，请检查网络或文件格式");
}

const handleExceed = () => {
  ElMessage.warning(`最多只能上传一个文件，请删除后再上传`);
};

const beforeRemove = (uploadFile, uploadFiles) => {
  return ElMessageBox.confirm(`确定要删除 ${uploadFile.name} 这个文件吗?`).then(
    () => true,
    () => false
  );
};

const customUpload = async (params) => {
  const file = params;

  try {
    const result = await upload(file);
    plusAndEditForm.avatar = result.data;
    ElMessage.success("上传成功");
  } catch (error) {
    ElMessage.error("上传失败: " + error.message);
  }
};
</script>

<style scoped lang="less">
.user-management-container {
  padding: 16px;

  .page-header {
    margin-bottom: 20px;

    h2 {
      margin: 0;
      font-size: 24px;
      font-weight: 600;
      color: #303133;
    }

    .subtitle {
      margin-top: 6px;
      font-size: 14px;
      color: #909399;
    }
  }

  .search-card {
    margin-bottom: 16px;

    .search-area {
      display: flex;
      flex-wrap: wrap;
      gap: 16px;

      .search-inputs {
        display: flex;
        flex-wrap: wrap;
        gap: 16px;
        flex: 3;

        .el-input {
          min-width: 200px;
          max-width: 250px;
        }
      }

      .filter-area {
        display: flex;
        gap: 16px;
        flex: 1;

        .el-select {
          min-width: 150px;
        }
      }
    }
  }

  .action-bar {
    margin-bottom: 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;

    .left-section {
      display: flex;
      gap: 8px;
    }
  }

  .table-card {
    margin-bottom: 16px;

    .el-table {
      margin-bottom: 16px;
    }

    .activity-img {
      width: 60px;
      height: 60px;
      border-radius: 6px;
      object-fit: cover;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
      transition: transform 0.3s;

      &:hover {
        transform: scale(1.1);
      }
    }

    .pagination-container {
      display: flex;
      justify-content: center;
      margin-top: 20px;
    }
  }

  :deep(.el-dialog__body) {
    padding-top: 10px;
    padding-bottom: 10px;
  }

  .dialog-footer {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    padding-top: 10px;
  }
}
</style>
